#include "stdafx.h"
#include "NHeap.h"


_HeapOption::_HeapOption()
	: _nInitialSize( 0 )
	, _nMaximumSize( 0 )
	, _bPrivateHeap( FALSE )
	, _bEnableLFH( FALSE )
{
}



_HeapOption::_HeapOption( size_t nInitialSize, size_t nMaximumSize, BOOL bPrivateHeap, BOOL bEnableLFH )
	: _nInitialSize( nInitialSize )
	, _nMaximumSize( nMaximumSize )
	, _bPrivateHeap( bPrivateHeap )
	, _bEnableLFH( bEnableLFH )
{
}



BOOL _HeapOption::IsValid()
{
	if ( TRUE == _bPrivateHeap )
	{
		if ( ( 0 == _nInitialSize ) || ( 0 == _nMaximumSize ) ) 
		{
			return FALSE;
		}
	}

	return TRUE;
}






CNHeap::CNHeap()
	: m_hHeap( nullptr )
	, m_HeapOption( HEAP_OPTION() )
{
}



CNHeap::~CNHeap()
{
}



eHeapCreationError CNHeap::Create( HEAP_OPTION& HeapOption )
{
	if ( nullptr != m_hHeap )
	{
		return eHeapErrHandleIsAlreadyExist;
	}

	if ( FALSE == HeapOption.IsValid() )
	{
		return eHeapErrInvalidOption;
	}

	m_HeapOption = HeapOption;

	m_hHeap = (TRUE == m_HeapOption._bPrivateHeap) ? 
						::HeapCreate( 0, m_HeapOption._nInitialSize, 0 ) : 
						::GetProcessHeap();

	if ( nullptr == m_hHeap )
	{
		return eHeapErrFailedToGetHeapHandle;
	}

	if ( TRUE == m_HeapOption._bEnableLFH )
	{
		ULONG ulHeapInfo = 2;	// enable LFH
		BOOL bRet = ::HeapSetInformation( m_hHeap, HeapCompatibilityInformation, &ulHeapInfo, sizeof(ulHeapInfo) );
		if ( FALSE == bRet )
		{
			Destroy();
			return eHeapErrFailedToSetLFH;
		}
	}

	return eHeapErrCreateSucceeded;
}



void CNHeap::Destroy()
{
	if (( nullptr != m_hHeap ) &&
		( TRUE == m_HeapOption._bPrivateHeap) )
	{
		::HeapDestroy( m_hHeap );
	}

	m_hHeap = nullptr;
}



void* CNHeap::Alloc( size_t  nSize )
{
	if ( nullptr == m_hHeap )
	{
		return nullptr;
	}

	return ::HeapAlloc( m_hHeap, 0, nSize );
}



void CNHeap::Free( LPVOID lpMem )
{
	if ( nullptr == m_hHeap )
	{
		return;
	}

	::HeapFree( m_hHeap, 0, lpMem );
}
